package com.doge.calcalbum.business.guide

import android.animation.Animator
import android.animation.AnimatorListenerAdapter
import android.animation.ValueAnimator
import android.content.Context
import android.os.Handler
import android.os.Looper
import android.util.AttributeSet
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.view.animation.AccelerateDecelerateInterpolator
import android.view.animation.DecelerateInterpolator
import androidx.constraintlayout.widget.ConstraintLayout
import androidx.core.view.isVisible
import com.doge.calcalbum.business.calc.CalcController
import com.doge.calcalbum.databinding.LayoutGuideCalcBinding
import com.doge.calcalbum.utils.dp
import com.doge.calcalbum.utils.spReadBoolean
import com.doge.calcalbum.utils.spWrite

class GuideCalcLayout @JvmOverloads constructor(
    context: Context,
    attrs: AttributeSet? = null
) : ConstraintLayout(context, attrs) {
    interface Callback {
        fun invoke(num: Int)
    }

    private val binding = LayoutGuideCalcBinding.inflate(LayoutInflater.from(context), this)
    private var animator1: ValueAnimator? = null
    private var animator2: ValueAnimator? = null
    private var animator3: ValueAnimator? = null
    private var animator4: ValueAnimator? = null
    private var animator5: ValueAnimator? = null
    private var animator6: ValueAnimator? = null
    private var callback: Callback? = null
    fun setCallback(cb: Callback) {
        callback = cb
    }

    fun display() {
        viewHandler.sendEmptyMessage(msgDisplay)

        val anim1 = ValueAnimator.ofFloat(0f, 1f)
        anim1.duration = 400
        anim1.interpolator = DecelerateInterpolator()
        anim1.addUpdateListener {
            val p = it.animatedValue as Float
            binding.cover1.alpha = p
            binding.cover2.alpha = p
            binding.guideTip1.alpha = p
            binding.guideFinger1.alpha = p
        }
        animator1?.cancel()
        animator1 = anim1
        anim1.start()

        val anim2 = ValueAnimator.ofFloat(0f, 40.dp.toFloat())
        anim2.duration = 1000
        anim2.startDelay = 350
        anim2.repeatCount = ValueAnimator.INFINITE
        anim2.repeatMode = ValueAnimator.REVERSE
        anim2.interpolator = AccelerateDecelerateInterpolator()
        anim2.addUpdateListener {
            val p = it.animatedValue as Float
            binding.guideFinger1.translationY = p
        }
        animator2?.cancel()
        animator2 = anim2
        anim2.start()
    }


    private fun release() {
        animator1?.cancel()
        animator2?.cancel()
        animator3?.cancel()
        animator4?.cancel()
        animator5?.cancel()
        animator6?.cancel()
        callback = null
        viewHandler.removeMessages(msgDisplay)
        viewHandler.removeMessages(msgIntercept)
    }

    private val msgDisplay = 101
    private val msgIntercept = 102
    private val msgStep2 = 103
    private val viewHandler = Handler(Looper.getMainLooper()) {
        it.target.removeMessages(it.what)
        if (it.what == msgDisplay) {
            it.target.sendEmptyMessageDelayed(msgIntercept, 350)
        } else if (it.what == msgIntercept) {
            setDispatchNumListeners()
        } else if (it.what == msgStep2) {
            step2()
        }
        true
    }

    private fun setDispatchNumListeners() {
        binding.cover1.setOnClickListener {  }
        binding.cover2.setOnClickListener {  }
        binding.dot.setOnClickListener {  }

        binding.num0.setOnClickListener {
            callback?.invoke(1)
            hide()
        }
        binding.num1.setOnClickListener {
            callback?.invoke(1)
            hide()
        }
        binding.num2.setOnClickListener {
            callback?.invoke(2)
            hide()
        }
        binding.num3.setOnClickListener {
            callback?.invoke(3)
            hide()
        }
        binding.num4.setOnClickListener {
            callback?.invoke(4)
            hide()
        }
        binding.num5.setOnClickListener {
            callback?.invoke(5)
            hide()
        }
        binding.num6.setOnClickListener {
            callback?.invoke(6)
            hide()
        }
        binding.num7.setOnClickListener {
            callback?.invoke(7)
            hide()
        }
        binding.num8.setOnClickListener {
            callback?.invoke(8)
            hide()
        }
        binding.num9.setOnClickListener {
            callback?.invoke(9)
            hide()
        }
    }

    private fun hide() {
        viewHandler.sendEmptyMessageDelayed(msgStep2, 250)
        binding.num0.visibility = View.INVISIBLE
        binding.num1.visibility = View.INVISIBLE
        binding.num2.visibility = View.INVISIBLE
        binding.num3.visibility = View.INVISIBLE
        binding.num4.visibility = View.INVISIBLE
        binding.num5.visibility = View.INVISIBLE
        binding.num6.visibility = View.INVISIBLE
        binding.num7.visibility = View.INVISIBLE
        binding.num8.visibility = View.INVISIBLE
        binding.num9.visibility = View.INVISIBLE

        val anim1 = ValueAnimator.ofFloat(1f, 0f)
        anim1.duration = 200
        anim1.interpolator = DecelerateInterpolator()
        anim1.addUpdateListener {
            val p = it.animatedValue as Float
            binding.cover1.alpha = p
            binding.cover2.alpha = p
            binding.guideTip1.alpha = p
            binding.guideFinger1.alpha = p
        }
        anim1.addListener(object : AnimatorListenerAdapter() {
            private fun removeListeners() {
                binding.cover1.visibility = View.INVISIBLE
                binding.cover2.visibility = View.INVISIBLE
                binding.dot.visibility = View.INVISIBLE
            }
            override fun onAnimationCancel(animation: Animator?) = removeListeners()
            override fun onAnimationEnd(animation: Animator?) = removeListeners()
        })
        animator1?.cancel()
        animator1 = anim1
        anim1.start()
        animator2?.cancel()


    }


    override fun onDetachedFromWindow() {
        super.onDetachedFromWindow()
        release()
    }
    companion object {
        fun completed() = spWrite("c", false,"g")
        private val firstTime: Boolean get() = spReadBoolean("c", true,"g")
        fun attach(view: ViewGroup): GuideCalcLayout? {
            if (firstTime && !CalcController.hasPass) {
                val viewGuide = GuideCalcLayout(view.context)
                view.addView(viewGuide)
                viewGuide.display()
                return viewGuide
            }
            return null
        }
    }
    
    private fun step2() {
        val anim3 = ValueAnimator.ofFloat(0f, 1f)
        anim3.duration = 400
        anim3.interpolator = DecelerateInterpolator()
        anim3.addUpdateListener {
            val p = it.animatedValue as Float
            binding.guideTip2.alpha = p
            binding.guideFinger2.alpha = p
        }
        animator3?.cancel()
        animator3 = anim3
        anim3.start()

        val anim4 = ValueAnimator.ofFloat(1f, 1.12f)
        anim4.duration = 800
        anim4.startDelay = 50
        anim4.repeatCount = ValueAnimator.INFINITE
        anim4.repeatMode = ValueAnimator.REVERSE
        anim4.interpolator = AccelerateDecelerateInterpolator()
        anim4.addUpdateListener {
            val p = it.animatedValue as Float
            binding.guideTip2.scaleX = p
            binding.guideTip2.scaleY = p
        }
        animator4?.cancel()
        animator4 = anim4
        anim4.start()

        val anim5 = ValueAnimator.ofFloat(0f, 15.dp.toFloat())
        anim5.duration = 1000
        anim5.startDelay = 350
        anim5.repeatCount = ValueAnimator.INFINITE
        anim5.repeatMode = ValueAnimator.REVERSE
        anim5.interpolator = AccelerateDecelerateInterpolator()
        anim5.addUpdateListener {
            val p = it.animatedValue as Float
            binding.guideFinger2.translationY = p
        }
        animator5?.cancel()
        animator5 = anim5
        anim5.start()

        val anim6 = ValueAnimator.ofFloat(0f, 0.8f)
        anim6.duration = 1000
        anim6.startDelay = 350
        anim6.repeatCount = ValueAnimator.INFINITE
        anim6.repeatMode = ValueAnimator.REVERSE
        anim6.interpolator = AccelerateDecelerateInterpolator()
        anim6.addUpdateListener {
            val p = it.animatedValue as Float
            binding.animPercent.alpha = p
        }
        animator6?.cancel()
        animator6 = anim6
        anim6.start()
    }
    
}